package com.mgface.zookeeper.premitive;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
/**
 * 避免通知所有的节点，只关注自己上一个节点(羊群效应)
 * @author user
 *
 */
public class 任务热备份2 {
	private static Logger log = Logger.getLogger(任务热备份2.class);
	private static ZooKeeper client;
	private static String path = "/zk";
	private static String newpath;

	public static void main(String[] args) throws Exception {
		CountDownLatch on = new CountDownLatch(1);
		client = new ZooKeeper("localhost:2181,localhost:2182,localhost:2183", 10_000, e -> {
			try {
				if (e.getState() == KeeperState.SyncConnected) {
					switch (e.getType()) {
					case None:
						if (e.getPath() == null) {
							on.countDown();
						}
						break;
					case NodeDeleted:
						log.info("节点:" + e.getPath() + "被删除");
						List<String> nodes = client.getChildren(path, false);
						Collections.sort(nodes);
						String replacePath = newpath.replace(path+"/","");//获得节点的名称
						int index  = nodes.indexOf(replacePath);//获得节点的下标
						if(index==0){
							client.setData(newpath, "master".getBytes(), -1);//如果为0说明是最小节点，设置为master
						}else{
							String upno = nodes.get(index-1);//获得上个节点的名称
							String fullName = path+"/"+upno;//获得上个节点的全名称
							client.exists(fullName, true);//添加监控
						}
						log.info("《监控》当前节点:"+newpath+"值:"+new String(client.getData(newpath, false, null)));
						break;
					default:
						break;
					}
				}
			} catch (Exception error) {
				error.getMessage();
			}

		});
		log.info("ZK状态:" + client.getState().toString());
		on.await();
		log.info("zookeeper session 建立完成");
		Stat stat = client.exists(path, false);
		if (stat == null) {
			client.create(path, "root".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
		}
		newpath = client.create(path + "/z2", "".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
		log.info(newpath);
		List<String> nodes = client.getChildren(path, false);
		Collections.sort(nodes);//进行自然排序，按照最小节点优先算法
		String replacePath = newpath.replace(path+"/","");//得到临时节点名称
		int index  = nodes.indexOf(replacePath);//获取临时节点的下标
		if(index==0){//如果为0的话，说明当前节点为最小，设置master
			client.setData(newpath, "master".getBytes(), -1);
		}else{//否则，监听它上一个节点
			String upno = nodes.get(index-1);//获得上个节点的节点名称
			String fullName = path+"/"+upno;//获得上个节点的全路径
			client.exists(fullName, true);//添加监控上个节点的操作（set,update,delete）
			client.setData(newpath, "slave".getBytes(), -1);//设置当前节点为master
		}
		log.info("当前节点:"+newpath+",值:"+new String(client.getData(newpath, false, null)));
		TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
	}
}
